package com.cloudfun.campusshare.device.protocol;

import com.aliyuncs.AcsRequest;
import com.aliyuncs.AcsResponse;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.exceptions.ServerException;
import com.aliyuncs.iot.model.v20180120.*;
import com.cloudfun.campusshare.common.constant.Code;
import com.cloudfun.campusshare.common.exception.BusinessException;
import com.cloudfun.campusshare.common.response.PageResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * Created by Huqin on 2020/2/5
 */
@Slf4j
@Service
public class AliyunIotService {

    @Autowired
    private IAcsClient iAcsClient;

    private static final String regionId = "cn-shanghai";

    /**
     * 创建产品
     *
     * @param productName
     * @return
     */
    public boolean createProduct(String productName) {
        CreateProductRequest request = new CreateProductRequest();
        request.setProductName(productName);
        //0：设备。设备不能挂载子设备。可以直连物联网平台，也可以作为网关的子设备连接物联网平台。
        //1：网关。网关可以挂载子设备，具有子设备管理模块，维持子设备的拓扑关系，和将拓扑关系同步到物联网平台。
        request.setNodeType(1);
        request.setDataFormat(1);
        CreateProductResponse response = this.execute(request);
        if (!response.getSuccess()) {
            log.error("请求阿里云IOT：ErrCode: {}, ErrMsg: {}, RequestId:{}", response.getCode(), response.getErrorMessage(), response.getRequestId());
            throw new BusinessException(Code.SYSTEM_ERROR);
        }
        return true;
    }

    /**
     * 注册设备
     *
     * @param productKey
     * @param deviceName
     * @return
     */
    public boolean registerDevice(String productKey, String deviceName) {
        RegisterDeviceRequest request = new RegisterDeviceRequest();
        request.setRegionId(regionId);
        request.setProductKey(productKey);
        request.setDeviceName(deviceName);
        RegisterDeviceResponse response = this.execute(request);
        if (!response.getSuccess()) {
            log.error("请求阿里云IOT：ErrCode: {}, ErrMsg: {}, RequestId:{}", response.getCode(), response.getErrorMessage(), response.getRequestId());
            throw new BusinessException(Code.SYSTEM_ERROR);
        }
        return true;
    }

    /**
     * 批量检查设备名
     *
     * @param productKey
     * @param deviceNames 单次调用，最多能传入1,000个设备名称
     * @return applyId
     */
    public Long batchCheckDeviceNames(String productKey, List<String> deviceNames) {
        BatchCheckDeviceNamesRequest request = new BatchCheckDeviceNamesRequest();
        request.setRegionId(regionId);
        request.setProductKey(productKey);
        request.setDeviceNames(deviceNames);
        BatchCheckDeviceNamesResponse response = this.execute(request);
        if (!response.getSuccess()) {
            log.error("请求阿里云IOT：ErrCode: {}, ErrMsg: {}, RequestId:{}",
                    response.getCode(), response.getErrorMessage(), response.getRequestId());
            throw new BusinessException(Code.SYSTEM_ERROR);
        }
        BatchCheckDeviceNamesResponse.Data data = response.getData();
        return data.getApplyId();
    }

    /**
     * 批量注册设备
     *
     * @param productKey
     * @param applyId
     * @return
     */
    public boolean batchRegisterDeviceWithApplyId(String productKey, Long applyId) {
        BatchRegisterDeviceWithApplyIdRequest request = new BatchRegisterDeviceWithApplyIdRequest();
        request.setRegionId(regionId);
        request.setProductKey(productKey);
        request.setApplyId(applyId);
        BatchRegisterDeviceWithApplyIdResponse response = this.execute(request);
        if (!response.getSuccess()) {
            log.error("请求阿里云IOT：ErrCode: {}, ErrMsg: {}, RequestId:{}",
                    response.getCode(), response.getErrorMessage(), response.getRequestId());
            throw new BusinessException(Code.SYSTEM_ERROR);
        }
        return true;
    }

    /**
     * 批量注册设备状态查询
     *
     * @param productKey
     * @param applyId
     * @return
     */
    public QueryBatchRegisterDeviceStatusResponse.Data queryBatchRegisterDeviceStatus(String productKey, Long applyId) {
        QueryBatchRegisterDeviceStatusRequest request = new QueryBatchRegisterDeviceStatusRequest();
        request.setRegionId(regionId);
        request.setProductKey(productKey);
        request.setApplyId(applyId);
        QueryBatchRegisterDeviceStatusResponse response = this.execute(request);
        if (!response.getSuccess()) {
            log.error("请求阿里云IOT：ErrCode: {}, ErrMsg: {}, RequestId:{}",
                    response.getCode(), response.getErrorMessage(), response.getRequestId());
            throw new BusinessException(Code.SYSTEM_ERROR);
        }
        return response.getData();
    }

    /**
     * 批量注册设备，设备名称随机
     *
     * @param productKey
     * @param count      取值不能大于1,000
     * @return
     */
    public Long batchRegisterDevice(String productKey, int count) {
        BatchRegisterDeviceRequest request = new BatchRegisterDeviceRequest();
        request.setRegionId(regionId);
        request.setProductKey(productKey);
        request.setCount(count);
        BatchRegisterDeviceResponse response = this.execute(request);
        if (!response.getSuccess()) {
            log.error("请求阿里云IOT：ErrCode: {}, ErrMsg: {}, RequestId:{}",
                    response.getCode(), response.getErrorMessage(), response.getRequestId());
            throw new BusinessException(Code.SYSTEM_ERROR);
        }
        return response.getData().getApplyId();
    }

    /**
     * 查询设备
     *
     * @param productKey
     * @param applyId
     * @param pageSize
     * @param currentPage
     * @return
     */
    public PageResult<QueryPageByApplyIdResponse.ApplyDeviceInfo> queryPageByApplyId(String productKey, Long applyId, int pageSize, int currentPage) {
        QueryPageByApplyIdRequest request = new QueryPageByApplyIdRequest();
        request.setRegionId(regionId);
        request.setApplyId(applyId);
        request.setPageSize(pageSize);
        request.setCurrentPage(currentPage);
        QueryPageByApplyIdResponse response = this.execute(request);
        if (!response.getSuccess()) {
            log.error("请求阿里云IOT：ErrCode: {}, ErrMsg: {}, RequestId:{}",
                    response.getCode(), response.getErrorMessage(), response.getRequestId());
            throw new BusinessException(Code.SYSTEM_ERROR);
        }
        PageResult<QueryPageByApplyIdResponse.ApplyDeviceInfo> result = new PageResult<>();
        result.setElements(response.getApplyDeviceList());
        result.setTotalSize(response.getTotal());
        return result;
    }

    /**
     * 获取设备状态
     *
     * @param productKey
     * @param deviceName
     * @return 设备状态。取值： ONLINE：设备在线。 OFFLINE：设备离线。 UNACTIVE：设备未激活。 DISABLE：设备已禁用。
     */
    public String getDeviceStatus(String productKey, String deviceName) {
        GetDeviceStatusRequest request = new GetDeviceStatusRequest();
        request.setProductKey(productKey);
        request.setDeviceName(deviceName);
        GetDeviceStatusResponse response = this.execute(request);
        if (!response.getSuccess()) {
            log.error("请求阿里云IOT：ErrCode: {}, ErrMsg: {}, RequestId:{}",
                    response.getCode(), response.getErrorMessage(), response.getRequestId());
            throw new BusinessException(Code.SYSTEM_ERROR);
        }
        return response.getData().getStatus();
    }

    /**
     * 删除设备
     *
     * @param productKey
     * @param deviceName
     * @return
     */
    public boolean deleteDevice(String productKey, String deviceName) {
        DeleteDeviceRequest request = new DeleteDeviceRequest();
        request.setProductKey(productKey);
        request.setDeviceName(deviceName);
        DeleteDeviceResponse response = this.execute(request);
        return response.getSuccess();
    }

    private <T extends AcsResponse> T execute(AcsRequest<T> request) {
        try {
            return iAcsClient.getAcsResponse(request);
        } catch (ServerException e) {
            log.error("请求阿里云IOT异常：", e);
            throw new BusinessException(Code.SYSTEM_ERROR);
        } catch (ClientException e) {
            log.error("请求阿里云IOT异常: ErrCode: {}, ErrMsg: {}, RequestId:{}", e.getErrCode(), e.getErrMsg(), e.getRequestId());
            throw new BusinessException(Code.SYSTEM_ERROR);
        }
    }

}
